
import { _config, _widgetTemplate, getWidgetNode } from './config.js'
import utils from '@/plugins/utils/utils.js'
/**
 * 工作原理 - 类vue
 * 修改design.widgets后，监听到 - 根据多对应的wid修改显示结果
 */
let $this = this
export default class design {
  /* 区域选择 */

  // 全局参数
  config = {
    ..._config,
    template: { ..._widgetTemplate },
    root: 'widget-list', // 根节点
    clazzs: ['widget', 'group', 'master'], // 类别 - widget（基础）、group（分组组合）、master
    zindexMax: 10, // 保存z-index的最大值，手动设置的除外
    // 仅做示例，
    lineType: {
      type: '', // 类型 - section：区块（红色+数字）； reference：参考线（蓝色）； distance：距离线（红色+数字）
      direction: '', // 方向 - horizontal：横线；vertical：竖线
      style: '', // 样式，border-style - dotted、solid、double、dashed

      // 大小
      width: 0,
      height: 0,

      // 位置
      x: 0,
      y: 0
    },
    size: {
      // 做8点定位使用
      left: 0,
      top: 0,

      width: 3000,
      height: 2000,
      // 宽的一半
      widthHalf: 1500,
      // 高的一半
      heightHalf: 1000
    }
  }
  /** 画布坐标 #canvas https://developer.mozilla.org/zh-CN/docs/Web/API/Element/getBoundingClientRect */
  coordinate = null // {x:0,y:0}
  //
  transformxy = null // 同上，为空，不做设置
  $root = null
  // 单项绑定 Proxy
  // 废弃
  widgets = []
  /* id: widget */
  widgetMap = {
    // 'widget_xxx':{}
  }
  // 鼠标状态，比如：左键按下 - wid+'_'+leftmousedown:true
  keyStatus = {}
  // diff算法，更新修改的数据
  constructor() {
    $this = this
    let _root = document.getElementById(this.config.root)
    if (!_root) {
      console.error('prototype - design - init error : not find element, document.getElementById(' + this.config.root + ')')
      return
    }

    // 清空子节点
    // let childs = _root.childNodes;
    // utils.$info('root init and child count', childs.length)
    // for (let i = 0; i < childs.length; i++) {
    //   _root.removeChild(childs[i]);
    // }


    this.$root = _root

    // 画布坐标
    this.coordinate = {
      x: _root.getBoundingClientRect().x,
      y: _root.getBoundingClientRect().y
    }

    // this.widgetMap = new Proxy(this.widgetMap, {
    //     /**
    //      * 拦截set
    //      * @param {Object} target widgetMap
    //      * @param {String} key  widget.id
    //      * @param {Object} value widget对象
    //      */
    //     set: function (target, key, value) {
    //         let success = Reflect.set(target, key, value)
    //         // 在创建新的widget时，默认选中该widget
    //         $nuxt.$emit('widget-select', target[key])
    //         return success
    //     }
    // })
  }

  /**
   * 在画布上创建widget
   * @param {String} code  同type，矩形、文字、直线、图片等
   * @param {String} clazz 分类，widget、group、master
   */
  createWidget(args) {
    if (!args) {
      // 如果不存在
      utils.info({ err: true }, 'createWidget - 缺少参数')
      return false;
    }

    // 如果存在，则根据args.code创建
    if (args.code) {
      // 计算坐标 -
      let _x = args.x - this.coordinate.x
      let _y = args.y - this.coordinate.y
      utils.log('开始创建', {
        'args.e': args.e,
        coordinate: this.coordinate,
        '相对坐标': { x: _x, y: _y }
      })

      // 创建
      let wid = this.idGenerator(args.clazz)

      // TODO 根据code判断widget
      let node_args = { wid: wid, text: '111' }
      let node = getWidgetNode(args.code, node_args)


      let zindex = this.config.zindexMax++
      // 设置node的样式，如： left,top width,height z-index
      let _style = []
      _style.push('width:100px')
      _style.push('height:100px')
      _style.push('left:' + _x + 'px')
      _style.push('top:' + _y + 'px')
      _style.push('z-index:' + zindex)
      _style.push('text-align: center;')

      _style.push('position:absolute;')

      node.setAttribute('style', _style.join(';'));

      let _children_style = []
      _children_style.push('width:100px')
      _children_style.push('height:100px')
      _children_style.push('top:0px')
      _children_style.push('left:0px')
      _children_style.push('z-index:' + zindex)
      _children_style.push('opacity:1')
      _children_style.push('padding:0px')
      _children_style.push('font-size:14px')

      // _children_style.push('justify-content: center')
      // _children_style.push('align-items: flex-start')

      node.children[0].setAttribute('style', _children_style.join(';'));
      // 描述widget的数据
      let _widget = {
        id: wid,
        wid: wid,
        clazz: args.clazz || 'widget',
        type: args.type || args.code,
        code: args.code || args.type,
        widget: null,
        postion: 'absolute',
        name: '矩形', // TODO 根据code获取名称
        config: {
          left: _x,
          top: _y,
          width: 100,
          height: 100,
          zindex: zindex,

          //
          ...node_args
        },
        element: node,
        link: null,
        animation: null
      }
      // 设置8点定位
      this.setPostionData(_widget.config)

      // 设置事件 -
      node.onmousedown = function (e) {
        // 判断是否按下shift键
        let isShift = $nuxt.$store.state.design.keydown['shift']
        if (!isShift) {
          $nuxt.$emit('widget-select', _widget.wid)
        } else {
          $nuxt.$emit('widget-add-select', _widget.wid)
        }
        // 缓存鼠标按下后的位置，和移动后的位置
        $this.keyStatus[wid + '_leftmousedown'] = { x: e.clientX, y: e.clientY }
      }
      // 鼠标抬起
      node.onmouseup = function () {
        // 停止拖动
        $nuxt.$store.commit('design/moving', false)

        delete $this.keyStatus[wid + '_leftmousedown']
      }
      // 双击
      node.ondblclick = function () {
        $nuxt.$emit('widget-dblclick', _widget.wid)
      }

      // 鼠标移入事件
      node.onmouseover = function () {
        $nuxt.$emit('widget-hover', _widget.wid)
      }
      // 鼠标移出事件
      node.onmouseout = function () {
        $nuxt.$emit('widget-unhover', _widget.wid)
      }
      // 鼠标移动
      node.onmousemove = function (e) {
        // 判断是否按下鼠标
        if ($this.keyStatus[wid + '_leftmousedown']) {
          // 当前鼠标的位置
          let mouseTop = e.clientY;
          let mouseLeft = e.clientX;

          // 鼠标按下时的位置
          let disX = $this.keyStatus[wid + '_leftmousedown'].x
          let disY = $this.keyStatus[wid + '_leftmousedown'].y

          // 计算结果
          let nl = mouseLeft - disX
          let nt = mouseTop - disY
          // console.log(nl,nt)
          $this.keyStatus[wid + '_leftmousedown'].x = mouseLeft
          $this.keyStatus[wid + '_leftmousedown'].y = mouseTop
          // 使用 left==-1,top==1的方式，如：向右下移动：left:1,top:1
          // 当选中多个widget移动时，鼠标按在哪个widget上，则触发该事件，不会触发多个
          $nuxt.$emit('widget-move', { 'wid': wid, 'action': 'move', 'left': nl, 'top': nt })
        }
      }


      // 可以使用
      // console.log('$nuxt',$nuxt.$store)
      // 使用方法设置
      // 默认获取焦点
      // console.log('node', node)
      // console.log('root', this.$root)
      this.$root.append(node);
      this.widgetMap[wid] = _widget
      // 选中该widget
      $nuxt.$emit('widget-select', wid)

      $nuxt.$emit('widget-created', _widget)
    } else {
      $nuxt.$emit('console.prod', {
        err: 'createWidget - 参数错误',
        source: '@/plugins/design/index.js#createWidget()'
      })
    }
    // TODO
  }

  updateWidget(args) {
    if (args.action == 'resize') {
      this._resizeWidget(args.wid, args)
    } else if (args.action == 'move') {
      // TODO 移动方向
      this._moveSelectsWidget(args.left, args.top)
    }
    // $nuxt.$emit('widget-update',args.wid)
  }

  // 计算参考线
  getLines() {
    // 已经选择的
    return $nuxt.$store.state.design.selects
  }

  // 设置8点定位
  setPostionData(config) {
    let _data = this.getPositionData(config)
    config = Object.assign(config, _data)
  }

  // 获取8点定位
  getPositionData(config) {
    if (!config || !config.height || !config.width || !config.left && config.left !== 0 || !config.top && config.top !== 0) {
      console.error('获取8点定位，参数错误: ', config)
    }
    // height、left、top、width
    return {
      width: config.width,
      height: config.height,
      // ====
      // 左上、右上
      ltx: config.left,
      lty: config.top,
      rtx: config.left + config.width,
      rty: config.top,

      // 左中、右中
      lcx: config.left,
      lcy: config.top + Math.floor(config.height / 2),
      rcx: config.left + config.width,
      rcy: config.top + Math.floor(config.height / 2),

      // 上中、下中
      ctx: config.left + Math.floor(config.width / 2),
      cty: config.top,
      bcx: config.left + Math.floor(config.width / 2),
      bcy: config.top + config.height,

      // 左下、右下
      lbx: config.left,
      lby: config.top + config.height,
      rbx: config.left + config.width,
      rby: config.top + config.height
    }
  }
  /**
   * TODO 异步/同步：计算参考线（先使用异步）
   * 1、获取当前选中的坐标 state.totalSelect
   * 2、获取剩下其他的widget坐标
   * 3、如何计算？？
   * 3.1、
   * 4、更新参考线（不同类型）
   */
  calculationRefLines() {
    // 选中坐标 - 最外层坐标
    let totalSelect = $nuxt.$store.state.design.totalSelect
    let _source = this.getPositionData(totalSelect)
    // height: 100
    // left: 464
    // top: 194
    // width: 100
    // 最外框。可能是单选、也可能是多选
    let selects = this.getLines()
    // 未选中的widget
    let _unselected = this.getOther(selects)

    // 添加画布的8点定位
    _unselected.push({ config: this.getPositionData(this.config.size) })
    // 算法（暂时没用到） https://blog.csdn.net/sflf36995800/article/details/82263221


    let lines = []

    // 未选中
    // TODO 优化 - 条件互斥，如：横线时，上比上和中比上就是互斥
    for (let i = 0; i < _unselected.length; i++) {
      // 如何计算参考线？？
      let _target = _unselected[i].config
      // _target.xxx = 'xxxx'
      // 优化，在组件创建、移动时获取8点定位
      // 比较x，生成竖线 x - ltx、tcx、rtx


      /* 左 比 左 */
      if (_source.ltx == _target.ltx) {
        /*
            |
            |
        */
        if (_source.lty > _target.lby) {
          /* 在下面 */
          // 参考线
          lines.push(this.createLine('reference', 'vertical', _target.ltx, _target.lty, _target.height))
          lines.push(this.createLine('reference', 'vertical', _source.ltx, _source.lty, _source.height))
          // 距离线
          lines.push(this.createLine('distance', 'vertical', _target.lbx, _target.lby, _source.lty - _target.lby))

        } else if (_source.lby < _target.lty) {
          /* 在上面 */
          // 参考线
          lines.push(this.createLine('reference', 'vertical', _target.ltx, _target.lty, _target.height))
          lines.push(this.createLine('reference', 'vertical', _source.ltx, _source.lty, _source.height))
          // 距离线
          lines.push(this.createLine('distance', 'vertical', _source.lbx, _source.lby, _target.lty - _source.lby))

        } else {
          /* 参考线 */
          let minY = _source.lty > _target.lty ? _target.lty : _source.lty
          let maxY = _source.lby > _target.lby ? _source.lby : _target.lby
          let refLen = maxY - minY
          // 参考线没有长度
          lines.push(this.createLine('reference', 'vertical', _source.ltx, minY, refLen))
          /*
              距离线
              上y 和 上y 之间的距离
              下y 和 下y 之间的距离
          */
          // 上y 和 上y 之间的距离
          let len1 = Math.abs(_target.lty - _source.lty)
          lines.push(this.createLine('distance', 'vertical', _source.ltx, minY, len1))

          // 下y 和 下y 之间的距离
          let len2 = Math.abs(_target.lby - _source.lby)
          lines.push(this.createLine('distance', 'vertical', _source.ltx, maxY - len2, len2))
        }

      }
      /* 中间 比 左 */
      else if (_source.ctx == _target.ltx) {

        if (_source.cty > _target.lby) {
          /* 在下面 */
          // 参考线
          lines.push(this.createLine('reference', 'vertical', _target.ltx, _target.lty, _target.height))
          lines.push(this.createLine('reference', 'vertical', _source.ctx, _source.cty, _source.height))
          // 距离线
          lines.push(this.createLine('distance', 'vertical', _target.lbx, _target.lby, _source.lty - _target.lby))

        } else if (_source.bcy < _target.lty) {
          /* 在上面 */
          // 参考线
          lines.push(this.createLine('reference', 'vertical', _target.ltx, _target.lty, _target.height))
          lines.push(this.createLine('reference', 'vertical', _source.ctx, _source.cty, _source.height))
          // 距离线
          lines.push(this.createLine('distance', 'vertical', _source.bcx, _source.lby, _target.lty - _source.lby))

        } else {
          /* 参考线 */
          let minY = _source.lty > _target.lty ? _target.lty : _source.lty
          let maxY = _source.lby > _target.lby ? _source.lby : _target.lby
          let refLen = maxY - minY
          // 参考线没有长度
          lines.push(this.createLine('reference', 'vertical', _source.bcx, minY, refLen))
          /*
              距离线
              上y 和 上y 之间的距离
              下y 和 下y 之间的距离
          */
          // 上y 和 上y 之间的距离
          let len1 = Math.abs(_target.lty - _source.lty)
          lines.push(this.createLine('distance', 'vertical', _source.bcx, minY, len1))

          // 下y 和 下y 之间的距离
          let len2 = Math.abs(_target.lby - _source.lby)
          lines.push(this.createLine('distance', 'vertical', _source.bcx, maxY - len2, len2))
        }
      }
      /* 右 比 左 */
      else if (_source.rtx == _target.ltx) {
        if (_source.cty > _target.lby) {
          /* 在下面 */
          // 参考线
          lines.push(this.createLine('reference', 'vertical', _target.ltx, _target.lty, _target.height))
          lines.push(this.createLine('reference', 'vertical', _source.rbx, _source.cty, _source.height))
          // 距离线
          lines.push(this.createLine('distance', 'vertical', _target.lbx, _target.lby, _source.lty - _target.lby))

        } else if (_source.bcy < _target.lty) {
          /* 在上面 */
          // 参考线
          lines.push(this.createLine('reference', 'vertical', _target.ltx, _target.lty, _target.height))
          lines.push(this.createLine('reference', 'vertical', _source.rbx, _source.cty, _source.height))
          // 距离线
          lines.push(this.createLine('distance', 'vertical', _source.rbx, _source.lby, _target.lty - _source.lby))

        } else {
          /* 参考线 */
          let minY = _source.lty > _target.lty ? _target.lty : _source.lty
          let maxY = _source.lby > _target.lby ? _source.lby : _target.lby
          let refLen = maxY - minY
          // 参考线没有长度
          lines.push(this.createLine('reference', 'vertical', _source.rbx, minY, refLen))
          /*
              距离线
              上y 和 上y 之间的距离
              下y 和 下y 之间的距离
          */
          // 上y 和 上y 之间的距离
          let len1 = Math.abs(_target.lty - _source.lty)
          lines.push(this.createLine('distance', 'vertical', _source.rbx, minY, len1))

          // 下y 和 下y 之间的距离
          let len2 = Math.abs(_target.lby - _source.lby)
          lines.push(this.createLine('distance', 'vertical', _source.rbx, maxY - len2, len2))
        }
      } // end 右 比 左


      /* 左 比 中 */
      if (_source.ltx == _target.ctx) {
        if (_source.lby < _target.cty) {
          // 在上面
          // 参考线
          lines.push(this.createLine('reference', 'vertical', _source.ltx, _source.lty, _source.height))
          lines.push(this.createLine('reference', 'vertical', _target.ctx, _target.cty, _target.height))
          // 距离线
          lines.push(this.createLine('distance', 'vertical', _source.lbx, _source.lby, _target.cty - _source.lby))
        } else if (_source.lty > _target.bcy) {
          // 在下面
          // 参考线
          lines.push(this.createLine('reference', 'vertical', _source.ltx, _source.lty, _source.height))
          lines.push(this.createLine('reference', 'vertical', _target.ctx, _target.cty, _target.height))

          // 距离线
          lines.push(this.createLine('distance', 'vertical', _target.bcx, _target.bcy, _source.lty - _target.bcy))
        } else {

          // 相交
          /* 参考线 */
          let minY = _source.lty > _target.lty ? _target.lty : _source.lty
          let maxY = _source.lby > _target.lby ? _source.lby : _target.lby
          let refLen = maxY - minY
          // 参考线 - 长度
          lines.push(this.createLine('reference', 'vertical', _source.ltx, minY, refLen))

          /*
              距离线
              左上y 和 中上y 之间的距离
              左下y 和 中下y 之间的距离
          */
          // 左上y 和 中上y 之间的距离
          let len1 = Math.abs(_target.lty - _source.cty)
          lines.push(this.createLine('distance', 'vertical', _source.ltx, minY, len1))

          // 左下y 和 中下y 之间的距离
          let len2 = Math.abs(_target.lty - _source.lty)
          lines.push(this.createLine('distance', 'vertical', _source.ltx, maxY - len2, len2))
        }
      }
      /* 中 比 中 */
      else if (_source.ctx == _target.ctx) {
        // 在上面
        if (_source.bcy < _target.cty) {
          // 在上面
          // 参考线
          lines.push(this.createLine('reference', 'vertical', _source.ctx, _source.cty, _source.height))
          lines.push(this.createLine('reference', 'vertical', _target.ctx, _target.cty, _target.height))
          // 距离线
          lines.push(this.createLine('distance', 'vertical', _source.bcx, _source.bcy, _target.cty - _source.bcy))
        } else if (_source.cty > _target.bcy) {
          // 在下面
          // 参考线
          lines.push(this.createLine('reference', 'vertical', _source.ctx, _source.cty, _source.height))
          lines.push(this.createLine('reference', 'vertical', _target.ctx, _target.cty, _target.height))

          // 距离线
          lines.push(this.createLine('distance', 'vertical', _target.bcx, _target.bcy, _source.cty - _target.bcy))
        } else {

          // 相交
          /* 参考线 */
          let minY = _source.cty > _target.lty ? _target.lty : _source.cty
          let maxY = _source.bcy > _target.lby ? _source.bcy : _target.lby
          let refLen = maxY - minY
          // 参考线 - 长度
          lines.push(this.createLine('reference', 'vertical', _source.ctx, minY, refLen))

          /*
              距离线
              左上y 和 中上y 之间的距离
              左下y 和 中下y 之间的距离
          */
          // 左上y 和 中上y 之间的距离
          let len1 = Math.abs(_target.lty - _source.cty)
          lines.push(this.createLine('distance', 'vertical', _source.ctx, minY, len1))

          // 左下y 和 中下y 之间的距离
          let len2 = Math.abs(_target.lty - _source.cty)
          lines.push(this.createLine('distance', 'vertical', _source.ctx, maxY - len2, len2))
        }
      }
      /* 右 比 中 */
      else if (_source.rtx == _target.ctx) {
        // 在上面
        if (_source.rby < _target.cty) {
          // 在上面
          // 参考线
          lines.push(this.createLine('reference', 'vertical', _source.rtx, _source.rtx, _source.height))
          lines.push(this.createLine('reference', 'vertical', _target.ctx, _target.cty, _target.height))
          // 距离线
          lines.push(this.createLine('distance', 'vertical', _source.rbx, _source.rby, _target.cty - _source.rby))
        } else if (_source.rty > _target.bcy) {
          // 在下面
          // 参考线
          lines.push(this.createLine('reference', 'vertical', _source.rtx, _source.rty, _source.height))
          lines.push(this.createLine('reference', 'vertical', _target.ctx, _target.cty, _target.height))

          // 距离线
          lines.push(this.createLine('distance', 'vertical', _target.bcx, _target.bcy, _source.rty - _target.bcy))
        } else {

          // 相交
          /* 参考线 */
          let minY = _source.rty > _target.cty ? _target.cty : _source.rty
          let maxY = _source.rby > _target.bcy ? _source.rby : _target.bcy

          let refLen = maxY - minY
          // 参考线
          lines.push(this.createLine('reference', 'vertical', _source.rtx, minY, refLen))

          /*
              距离线
          */
          let len1 = Math.abs(_target.cty - _source.rty)
          lines.push(this.createLine('distance', 'vertical', _source.rtx, minY, len1))

          let len2 = Math.abs(_target.bcy - _source.rby)
          console.log('maxY:', maxY, 'len2:', len2)
          lines.push(this.createLine('distance', 'vertical', _source.rtx, maxY - len2, len2))
        }
      }

      /* 左 比 右 */
      if (_source.ltx == _target.rtx) {
        if (_source.lby < _target.rty) {
          // 在上面
          // 参考线
          lines.push(this.createLine('reference', 'vertical', _source.ltx, _source.lty, _source.height))
          lines.push(this.createLine('reference', 'vertical', _target.rtx, _target.rty, _target.height))

          // 距离线
          lines.push(this.createLine('distance', 'vertical', _source.lbx, _source.lby, _target.rty - _source.lby))

        } else if (_source.lty > _target.rby) {
          // 在下面
          // 参考线
          lines.push(this.createLine('reference', 'vertical', _source.ltx, _source.lty, _source.height))
          lines.push(this.createLine('reference', 'vertical', _target.rtx, _target.rty, _target.height))

          // 距离线
          lines.push(this.createLine('distance', 'vertical', _target.rbx, _target.rby, _source.lty - _target.rby))

        } else {
          // 相交
          /* 参考线 */
          let minY = _source.lty > _target.rty ? _target.rty : _source.lty
          let maxY = _source.lby > _target.rby ? _source.lby : _target.rby
          let refLen = maxY - minY
          // 参考线
          lines.push(this.createLine('reference', 'vertical', _source.ltx, minY, refLen))

          /*
              距离线
          */
          let len1 = Math.abs(_target.rty - _source.lty)
          lines.push(this.createLine('distance', 'vertical', _source.ltx, minY, len1))

          let len2 = Math.abs(_target.rby - _source.lby)
          lines.push(this.createLine('distance', 'vertical', _source.ltx, maxY - len2, len2))
        }

      }

      /* 中 比 右 */
      else if (_source.ctx == _target.rtx) {
        if (_source.bcy < _target.rty) {
          // 在上面
          // 参考线
          lines.push(this.createLine('reference', 'vertical', _source.ctx, _source.cty, _source.height))
          lines.push(this.createLine('reference', 'vertical', _target.rtx, _target.rty, _target.height))

          // 距离线
          lines.push(this.createLine('distance', 'vertical', _source.bcx, _source.bcy, _target.rty - _source.bcy))

        } else if (_source.cty > _target.rby) {
          // 在下面
          // 参考线
          lines.push(this.createLine('reference', 'vertical', _source.ctx, _source.cty, _source.height))
          lines.push(this.createLine('reference', 'vertical', _target.rtx, _target.rty, _target.height))

          // 距离线
          lines.push(this.createLine('distance', 'vertical', _target.rbx, _target.rby, _source.cty - _target.rby))

        } else {
          // 相交
          /* 参考线 */
          let minY = _source.cty > _target.rty ? _target.rty : _source.cty
          let maxY = _source.bcy > _target.rby ? _source.bcy : _target.rby
          let refLen = maxY - minY
          // 参考线
          lines.push(this.createLine('reference', 'vertical', _source.ctx, minY, refLen))

          /*
              距离线
          */
          let len1 = Math.abs(_target.rty - _source.cty)
          lines.push(this.createLine('distance', 'vertical', _source.ctx, minY, len1))

          let len2 = Math.abs(_target.rby - _source.bcy)
          lines.push(this.createLine('distance', 'vertical', _source.ctx, maxY - len2, len2))
        }
      }
      /* 右 比 右 */
      else if (_source.rtx == _target.rtx) {
        if (_source.rby < _target.rty) {
          // 在上面
          // 参考线
          lines.push(this.createLine('reference', 'vertical', _source.rtx, _source.rty, _source.height))
          lines.push(this.createLine('reference', 'vertical', _target.rtx, _target.rty, _target.height))

          // 距离线
          lines.push(this.createLine('distance', 'vertical', _source.rbx, _source.rby, _target.rty - _source.bcy))

        } else if (_source.rty > _target.rby) {
          // 在下面
          // 参考线
          lines.push(this.createLine('reference', 'vertical', _source.rtx, _source.rty, _source.height))
          lines.push(this.createLine('reference', 'vertical', _target.rtx, _target.rty, _target.height))

          // 距离线
          lines.push(this.createLine('distance', 'vertical', _target.rbx, _target.rby, _source.cty - _target.rby))

        } else {
          // 相交
          /* 参考线 */
          let minY = _source.rty > _target.rty ? _target.rty : _source.rty
          let maxY = _source.rby > _target.rby ? _source.rby : _target.rby
          let refLen = maxY - minY
          // 参考线
          lines.push(this.createLine('reference', 'vertical', _source.rtx, minY, refLen))

          /*
              距离线
          */
          let len1 = Math.abs(_target.rty - _source.rty)
          lines.push(this.createLine('distance', 'vertical', _source.rtx, minY, len1))

          let len2 = Math.abs(_target.rby - _source.rby)
          lines.push(this.createLine('distance', 'vertical', _source.rtx, maxY - len2, len2))
          console.log('len1 len2', len1, len2)
        }
      }
      // ===================== end 横着比较，显示竖线 =======================

      // ===================== 竖着比较，显示横线 =======================
      /* 上比上 */
      if (_source.rty == _target.lty) {
        // 在左边
        if (_source.rtx < _target.ltx) {
          // 参考线
          lines.push(this.createLine('reference', 'horizontal', _source.ltx, _source.lty, _source.width))
          lines.push(this.createLine('reference', 'horizontal', _target.ltx, _target.lty, _target.width))

          // 距离线
          lines.push(this.createLine('distance', 'horizontal', _source.rtx, _source.rty, _target.ltx - _source.rtx))
        } else if (_source.ltx > _target.rtx) {
          // 在右边
          // 参考线
          lines.push(this.createLine('reference', 'horizontal', _source.ltx, _source.lty, _source.width))
          lines.push(this.createLine('reference', 'horizontal', _target.ltx, _target.lty, _target.width))

          // 距离线
          lines.push(this.createLine('distance', 'horizontal', _target.rtx, _target.rty, _source.ltx - _target.rtx))
        } else {
          // 相交
          /* 参考线 - 会被距离线覆盖一部分 */
          let minX = Math.min(_source.ltx, _target.ltx)
          let maxX = Math.max(_source.rtx, _target.rtx)
          let refLen = maxX - minX
          // 参考线
          lines.push(this.createLine('reference', 'horizontal', minX, _source.lty, refLen))

          /*
              距离线
          */
          let len1 = Math.abs(_target.ltx - _source.ltx)
          lines.push(this.createLine('distance', 'horizontal', minX, _source.lty, len1))

          let len2 = Math.abs(_target.rtx - _source.rtx)
          lines.push(this.createLine('distance', 'horizontal', maxX - len2, _source.rty, len2))
        }
      }
      /* 上比中 */
      else if (_source.rty == _target.lcy) {
        // 在左边
        if (_source.rtx < _target.lcx) {
          // 参考线
          lines.push(this.createLine('reference', 'horizontal', _source.ltx, _source.lty, _source.width))
          lines.push(this.createLine('reference', 'horizontal', _target.lcx, _target.lcy, _target.width))

          // 距离线
          lines.push(this.createLine('distance', 'horizontal', _source.rtx, _source.rty, _target.lcx - _source.rtx))
        }
        // 在右边
        else if (_source.ltx > _target.rtx) {
          // 参考线
          lines.push(this.createLine('reference', 'horizontal', _source.ltx, _source.lty, _source.width))
          lines.push(this.createLine('reference', 'horizontal', _target.lcx, _target.lcy, _target.width))

          // 距离线
          lines.push(this.createLine('distance', 'horizontal', _target.rcx, _target.rcy, _source.ltx - _target.rtx))

        }
        // 相交
        else {
          // 参考线
          let minX = Math.min(_source.ltx, _target.lcx)
          let maxX = Math.max(_source.rtx, _target.rcx)
          let refLen = maxX - minX
          lines.push(this.createLine('reference', 'horizontal', minX, _source.lty, refLen))
          // 距离线
          let len1 = Math.abs(_target.lcx - _source.ltx)
          lines.push(this.createLine('distance', 'horizontal', minX, _source.lty, len1))

          let len2 = Math.abs(_target.lcx - _source.rtx)
          lines.push(this.createLine('distance', 'horizontal', maxX - len2, _source.rty, len2))

        }
      }
      /* 上比下 */
      else if (_source.rty == _target.lby) {
        // 在左边
        if (_source.rtx < _target.lbx) {
          // 参考线
          lines.push(this.createLine('reference', 'horizontal', _source.ltx, _source.lty, _source.width))
          lines.push(this.createLine('reference', 'horizontal', _target.lbx, _target.lby, _target.width))

          // 距离线
          lines.push(this.createLine('distance', 'horizontal', _source.rtx, _source.rty, _target.lbx - _source.rtx))

        }
        // 在右边
        else if (_source.ltx > _target.rbx) {
          // 参考线
          lines.push(this.createLine('reference', 'horizontal', _source.ltx, _source.lty, _source.width))
          lines.push(this.createLine('reference', 'horizontal', _target.lbx, _target.lby, _target.width))

          // 距离线
          lines.push(this.createLine('distance', 'horizontal', _target.rbx, _target.rby, _source.ltx - _target.rbx))

        }
        // 相交
        else {
          // 参考线
          let minX = Math.min(_source.ltx, _target.lbx)
          let maxX = Math.max(_source.rtx, _target.rbx)
          let refLen = maxX - minX
          lines.push(this.createLine('reference', 'horizontal', minX, _source.lty, refLen))
          // 距离线
          let len1 = Math.abs(_target.lbx - _source.ltx)
          lines.push(this.createLine('distance', 'horizontal', minX, _source.lty, len1))

          let len2 = Math.abs(_target.rbx - _source.rtx)
          lines.push(this.createLine('distance', 'horizontal', maxX - len2, _source.rty, len2))

        }
      }

      /* 中比上 */
      if (_source.rcy == _target.lty) {
        // 在左边
        if (_source.rcx < _target.ltx) {
          // 参考线
          lines.push(this.createLine('reference', 'horizontal', _source.lcx, _source.lcy, _source.width))
          lines.push(this.createLine('reference', 'horizontal', _target.ltx, _target.lty, _target.width))

          // 距离线
          lines.push(this.createLine('distance', 'horizontal', _source.rcx, _source.rcy, _target.ltx - _source.rcx))

        }
        // 在右边
        else if (_source.lcx > _target.rtx) {
          // 参考线
          lines.push(this.createLine('reference', 'horizontal', _source.lcx, _source.lcy, _source.width))
          lines.push(this.createLine('reference', 'horizontal', _target.ltx, _target.lty, _target.width))

          // 距离线
          lines.push(this.createLine('distance', 'horizontal', _target.rtx, _target.rty, _source.lcx - _target.rtx))
        }
        // 相交
        else {
          let minX = Math.min(_source.lcx, _target.ltx)
          let maxX = Math.max(_source.rcx, _target.rtx)
          let refLen = maxX - minX
          // 参考线
          lines.push(this.createLine('reference', 'horizontal', minX, _source.lcy, refLen))

          // 距离线
          // 距离线
          let len1 = Math.abs(_target.ltx - _source.lcx)
          lines.push(this.createLine('distance', 'horizontal', minX, _source.lty, len1))

          let len2 = Math.abs(_target.rtx - _source.rcx)
          lines.push(this.createLine('distance', 'horizontal', minX - len2, _source.rty, len2))
        }
      }
      /* 中比中 */
      else if (_source.rcy == _target.lcy) {
        // 在左边
        if (_source.rcx < _target.lcx) {
          // 参考线
          lines.push(this.createLine('reference', 'horizontal', _source.lcx, _source.lcy, _source.width))
          lines.push(this.createLine('reference', 'horizontal', _target.lcx, _target.lcy, _target.width))

          // 距离线
          lines.push(this.createLine('distance', 'horizontal', _source.rcx, _source.rcy, _target.lcx - _source.rcx))

        }
        // 在右边
        else if (_source.lcx > _target.rcx) {
          // 参考线
          lines.push(this.createLine('reference', 'horizontal', _source.lcx, _source.lcy, _source.width))
          lines.push(this.createLine('reference', 'horizontal', _target.lcx, _target.lcy, _target.width))

          // 距离线
          lines.push(this.createLine('distance', 'horizontal', _target.rcx, _target.rcy, _source.lcx - _target.rcx))
        }
        // 相交
        else {
          let minX = Math.min(_source.lcx, _target.lcx)
          let maxX = Math.max(_source.rcx, _target.rcx)
          let refLen = maxX - minX
          // 参考线
          lines.push(this.createLine('reference', 'horizontal', minX, _source.lcy, refLen))

          // 距离线
          let len1 = Math.abs(_target.lcx - _source.lcx)
          lines.push(this.createLine('distance', 'horizontal', minX, _source.lcy, len1))

          let len2 = Math.abs(_target.rcx - _source.rcx)
          lines.push(this.createLine('distance', 'horizontal', maxX - len2, _source.rcy, len2))
        }
      }
      /* 中比下 */
      else if (_source.rcy == _target.lby) {
        // 在左边
        if (_source.rcx < _target.lbx) {
          // 参考线
          lines.push(this.createLine('reference', 'horizontal', _source.lcx, _source.lcy, _source.width))
          lines.push(this.createLine('reference', 'horizontal', _target.lbx, _target.lby, _target.width))

          // 距离线
          lines.push(this.createLine('distance', 'horizontal', _source.rcx, _source.rcy, _target.lbx - _source.rcx))

        }
        // 在右边
        else if (_source.lcx > _target.rbx) {
          // 参考线
          lines.push(this.createLine('reference', 'horizontal', _source.lcx, _source.lcy, _source.width))
          lines.push(this.createLine('reference', 'horizontal', _target.lbx, _target.lby, _target.width))

          // 距离线
          lines.push(this.createLine('distance', 'horizontal', _target.rbx, _target.rby, _source.lcx - _target.rbx))
        }
        // 相交
        else {
          let minX = Math.min(_source.lcx, _target.lbx)
          let maxX = Math.max(_source.rcx, _target.rbx)
          let refLen = maxX - minX
          // 参考线
          lines.push(this.createLine('reference', 'horizontal', minX, _source.lcy, refLen))

          // 距离线
          // 距离线
          let len1 = Math.abs(_target.lbx - _source.lcx)
          lines.push(this.createLine('distance', 'horizontal', minX, _source.lcy, len1))

          let len2 = Math.abs(_target.rbx - _source.rcx)
          lines.push(this.createLine('distance', 'horizontal', maxX - len2, _source.rcy, len2))
        }
      }


      /* 下比上 */
      if (_source.lby == _target.lty) {
        // 在左边
        if (_source.rbx < _target.ltx) {
          // 参考线
          lines.push(this.createLine('reference', 'horizontal', _source.lbx, _source.lby, _source.width))
          lines.push(this.createLine('reference', 'horizontal', _target.ltx, _target.lty, _target.width))

          // 距离线
          lines.push(this.createLine('distance', 'horizontal', _source.rbx, _source.rby, _target.ltx - _source.rbx))

        }
        // 在右边
        else if (_source.lbx > _target.rtx) {
          // 参考线
          lines.push(this.createLine('reference', 'horizontal', _source.lbx, _source.lby, _source.width))
          lines.push(this.createLine('reference', 'horizontal', _target.ltx, _target.lty, _target.width))

          // 距离线
          lines.push(this.createLine('distance', 'horizontal', _target.rtx, _target.rty, _source.lbx - _target.rtx))
        }
        // 相交
        else {
          let minX = Math.min(_source.lbx, _target.ltx)
          let maxX = Math.max(_source.rbx, _target.rtx)
          let refLen = maxX - minX
          // 参考线
          lines.push(this.createLine('reference', 'horizontal', minX, _source.lby, refLen))

          // 距离线
          // 距离线
          let len1 = Math.abs(_target.ltx - _source.lcx)
          lines.push(this.createLine('distance', 'horizontal', minX, _source.lby, len1))

          let len2 = Math.abs(_target.rtx - _source.rbx)
          lines.push(this.createLine('distance', 'horizontal', minX - len2, _source.rby, len2))
        }
      }
      /* 下比中 */
      else if (_source.lby == _target.lcy) {
        // 在左边
        if (_source.rbx < _target.lcx) {
          // 参考线
          lines.push(this.createLine('reference', 'horizontal', _source.lbx, _source.lby, _source.width))
          lines.push(this.createLine('reference', 'horizontal', _target.lcx, _target.lcy, _target.width))

          // 距离线
          lines.push(this.createLine('distance', 'horizontal', _source.rbx, _source.rby, _target.lcx - _source.rbx))

        }
        // 在右边
        else if (_source.lbx > _target.rcx) {
          // 参考线
          lines.push(this.createLine('reference', 'horizontal', _source.lbx, _source.lby, _source.width))
          lines.push(this.createLine('reference', 'horizontal', _target.lcx, _target.lcy, _target.width))

          // 距离线
          lines.push(this.createLine('distance', 'horizontal', _target.rcx, _target.rcy, _source.lbx - _target.rcx))
        }
        // 相交
        else {
          let minX = Math.min(_source.lbx, _target.lcx)
          let maxX = Math.max(_source.rbx, _target.rcx)
          let refLen = maxX - minX
          // 参考线
          lines.push(this.createLine('reference', 'horizontal', minX, _source.lby, refLen))

          // 距离线
          // 距离线
          let len1 = Math.abs(_target.lcx - _source.lcx)
          lines.push(this.createLine('distance', 'horizontal', minX, _source.lby, len1))

          let len2 = Math.abs(_target.rcx - _source.rbx)
          lines.push(this.createLine('distance', 'horizontal', minX - len2, _source.rby, len2))
        }
      }
      /* 下比下 */
      else if (_source.lby == _target.lby) {
        // 在左边
        if (_source.rbx < _target.lbx) {
          // 参考线
          lines.push(this.createLine('reference', 'horizontal', _source.lbx, _source.lby, _source.width))
          lines.push(this.createLine('reference', 'horizontal', _target.lbx, _target.lby, _target.width))

          // 距离线
          lines.push(this.createLine('distance', 'horizontal', _source.rbx, _source.rby, _target.lbx - _source.rbx))

        }
        // 在右边
        else if (_source.lbx > _target.rbx) {
          // 参考线
          lines.push(this.createLine('reference', 'horizontal', _source.lbx, _source.lby, _source.width))
          lines.push(this.createLine('reference', 'horizontal', _target.lbx, _target.lby, _target.width))

          // 距离线
          lines.push(this.createLine('distance', 'horizontal', _target.rbx, _target.rby, _source.lbx - _target.rbx))
        }
        // 相交
        else {
          let minX = Math.min(_source.lbx, _target.lbx)
          let maxX = Math.max(_source.rbx, _target.rbx)
          let refLen = maxX - minX
          // 参考线
          lines.push(this.createLine('reference', 'horizontal', minX, _source.lby, refLen))

          // 距离线
          let len1 = Math.abs(_target.lbx - _source.lbx)
          lines.push(this.createLine('distance', 'horizontal', minX, _source.lby, len1))

          let len2 = Math.abs(_target.rbx - _source.rbx)
          lines.push(this.createLine('distance', 'horizontal', maxX - len2, _source.rby, len2))
        }
      }
      // ===================== end 竖着比较，显示横线 =======================


      // TODO 设置参考线 - lines
      $nuxt.$store.commit('design/setLines', lines)
      // 计算
      // console.log('定位信息：', $nuxt.$store)

    }
  }

  /**
   * 创建参考线
   * <p>
   *  1、线 - 方向、位置、长度
   *  2、距离数字 - 位置
   * </p>
   * @param {*} type
   * @param {*} direction
   * @param {*} x
   * @param {*} y
   * @param {*} len
   */
  createLine(type, direction, x, y, len) {
    return {

      // 参考线不显示text，即长度的数字
      'showText': type !== 'reference',
      // 类型 - section：区块（红色+数字）； reference：参考线（蓝色），会被距离线覆盖； distance：距离线（红
      'type': type,
      // 方向
      'direction': direction, // 方向 - horizontal：横线；vertical：竖线
      // 长度
      'len': len,
      // 位置
      'x': x,
      'y': y,
      'px': {
        'len': len + 'px',
        'x': x + 'px',
        'y': y + 'px',
        // text-left
        'tx': direction == 'vertical' ? x - 20 + 'px' : x + len / 2 - 9 + 'px',
        // text-top
        'ty': direction == 'vertical' ? y + len / 2 - 9 + 'px' : y - 20 + 'px'
      }

    }
  }


  /**
   * 移动所有选中的widget
   * @param {Number} left 偏移量，只为 1,2,-1,-3等
   * @param {Number} top 同上
   */
  _moveSelectsWidget(left, top) {
    if (left == 0 && top == 0) {
      return true
    }
    // console.log('移动所有选中的', Math.random())
    // 所有选中的widget: 根据id获取widget
    let _selectWidgets = this.get($nuxt.$store.state.design.selects)
    for (let index in _selectWidgets) {
      let _widget = _selectWidgets[index]
      _widget.config.left = _widget.config.left + left
      _widget.element.style.left = _widget.config.left + 'px'


      _widget.config.top = _widget.config.top + top
      _widget.element.style.top = _widget.config.top + 'px'

      // 更新8点定位
      this.setPostionData(_widget.config)
    }
  }

  // 更改大小
  _resizeWidget(wid, args) {
    let _widget = this.get(wid)
    if (args.left) {
      _widget.config.left = args.left
      _widget.element.style.left = args.left + 'px'
    }
    if (args.top) {
      _widget.config.top = args.top
      _widget.element.style.top = args.top + 'px'
    }
    if (args.width) {
      _widget.config.width = args.width
      _widget.element.style.width = args.width + 'px'
      _widget.element.children[0].style.width = args.width + 'px'
    }
    if (args.height) {
      _widget.config.height = args.height
      _widget.element.style.height = args.height + 'px'
      _widget.element.children[0].style.height = args.height + 'px'
    }
    // 更新/设置8点定位
    this.setPostionData(_widget.config)
  }


  addWidget(_widget) {

  }

  push(widget) {
    // TODO 把widget绘制到画布
  }

  // 创建选择区域

  /**
   * 根据wid获取信息
   * @param {String} wid || array
   */
  get(wids) {
    if (!wids) {
      // 返回 [] ??
      return null
    }
    if (wids instanceof Array) {
      if (wids.length == 0) {
        return null
      }
      let result = []
      for (let index in wids) {
        result.push(this.widgetMap[wids[index]])
      }
      return result
    }
    return this.widgetMap[wids]
  }
  /**
   * 取反
   * @param {Array|String} wids 单个或数组
   */
  getOther(wids) {
    if (!wids) {
      return Object.values(this.widgetMap)
    }
    if (wids instanceof Array) {
      if (wids.length == 0) {
        return Object.values(this.widgetMap)
      }
      let result = []
      for (let key in this.widgetMap) {
        if (wids.indexOf(key) == -1) {
          // 如果wids里不存在key，则获取
          result.push(this.widgetMap[key])
        }
      }
      return result
    }
    let result = []
    for (let key in this.widgetMap) {
      if (wids != key) {
        // 如果wids里不存在key，则获取
        result.push(this.widgetMap[key])
      }
    }
    return result

  }
  /**
  * 取反
  * @param {Array|String} wids 单个或数组
  * @returns {key:[],value:[]}
  */
  getOther2(wids) {
    if (!wids) {
      return {
        key: Object.keys(this.widgetMap),
        value: Object.values(this.widgetMap)
      }
    }
    if (wids instanceof Array) {
      if (wids.length == 0) {
        return {
          key: Object.keys(this.widgetMap),
          value: Object.values(this.widgetMap)
        }
      }
      let keys = []
      let values = []
      for (let key in this.widgetMap) {
        if (wids.indexOf(key) == -1) {
          // 如果wids里不存在key，则获取
          values.push(this.widgetMap[key])
          keys.push(key)
        }
      }
      return {
        'key': keys,
        'value': values
      }
    }
    let keys = []
    let values = []
    for (let key in this.widgetMap) {
      if (wids != key) {
        // 如果wids里不存在key，则获取
        values.push(this.widgetMap[key])
        keys.push(key)
      }
    }
    return {
      'key': keys,
      'value': values
    }

  }

  getAll() {
    return this.widgetMap
  }
  getWidget(wid) {
    return this.get(wid)
  }
  /**
   * 获取$ele
   * @param {String} wid
   */
  getEle(wid) { }

  setZ(wid, zindex) {
    let _zindex = this.config.zindexMax
    if (zindex) {
      //
      _zindex = zindex
    }
    // 设置z-index
  }
  idGenerator(clazz) {

    let _id = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
      var r = Math.random() * 16 | 0, v = c == 'x' ? r : r & 0x3 | 0x8;
      return v.toString(16);
    });
    if (!clazz || clazz == 'widget') {
      // id: 唯一ID - 生成规则 - widget_xxx、group_xxx、
      return 'widget_' + _id
    }
  }
  // 将widget置顶 - 获取z-index最高的widget，然后+1
  // 根据手动输入的zinde置顶，


  /*
      点击某个元素后，回调有元素的信息，
      一个点击事件可以出发多个操作
  */

  /* 创建元素 - widget */
  /*
      widget: 部件。是prototype中最基本的元素，所有元素都由widget组成的

      部件是widget[]
      <div data-widget-wid="${id}">
  */

  // 虚拟节点 - vnode

  // id: 唯一ID - 生成规则 - widget_xxx、group_xxx、

  // wid: 同上，是id的别名

  // clazz: 类别 - widget（基础）、group（分组组合）、master

  // type: 类型 - 无（null）、在clazz==widget时，，矩形（rectangle）、文本（text）、线（line）、image_view（图片）、link、
  // triangle（三角形）、input（单行输入）、textarea（多行输入）、select（下拉框）、file_input（文件选择）、
  // map_view（地图）、carousel（轮播图）、icon（图标）

  // code: 类似type

  // widget[]: 子部件

  // postion: absolute

  // name: 名称 - 如：群组、图标、图标 Copy - 可更改

  // config: 重要的参数，从element中获取 {top,left,width,height,zindex(别名),z-index}

  // element: $ele
  // edit_element: $edit // 不确定是否废弃

  // link: 连接到-- 'prev_page'(上一页)、${page.id}

  // animation: null| {code:'animejs',data:'func:func10'}表示，平台需要有animejs，并且调用func10的方法；
  // {code:'animejs',data:'code:function(e){e......}'}表示，平台需要有animejs，并且动画代码为code:后面的内容
}